<template>
  <div class="page">
    <div class="box">
      <div class="box-page" :style="front.style">
        <div class="box-front">
          正面
        </div>
      </div>
      <div class="box-page" :style="back.style">
        <div class="box-back">
          反面
        </div>
      </div>
    </div>
    <div class="box1"></div>
    <button @click="step1">状态1</button>
    <button @click="step2">状态2</button>
    <button @click="step3">状态3</button>
    <button @click="step4">状态4</button>
  </div>
</template>
<script>
import { mat2d, vec2, vec3 } from '../../libs/glmatrix/gl-matrix-min.js'
export default {
  data() {
    return {
      front: {
        matrix: [],
        clip: '',
        style: {}
      },
      back: {
        matrix: [],
        clip: '',
        style: {}
      }
    }
  },
  methods: {
    reset() {
      this.front = {
        m1: mat2d.create(),
        m2: mat2d.create(),
        clip: [],
        style: {}
      }
      this.back = {
        m1: mat2d.create(),
        m2: mat2d.create(),
        clip: [],
        style: {}
      }
    },
    //状态1
    step1() {
      this.reset()
      let m = mat2d.create()
      mat2d.scale(m, m, [-1, 1])
      //反向翻转
      this.back.m1 = m
      this.buildStyle(this.back)
      this.buildStyle(this.front)
    },
    //状态2
    step2() {
      this.reset()
      this.back.clip = {}
      let m = mat2d.create()
      mat2d.translate(m, m, [-100, 0])
      this.back.m1 = m

      let front_m = mat2d.create()
      mat2d.translate(front_m, front_m, [-100, 0])
      mat2d.scale(front_m, front_m, [-1, 1])
      this.front.m1 = front_m
      this.buildStyle(this.back)
      this.buildStyle(this.front)
    },
    //状态3
    step3() {
      this.reset()
      let w = 100,
        h = 100
      let { rb, rt, lt, lb } = this.corrds
      //从左往右
      let s = [50, -50]
      let e = [0, 0]

      let x = (s[0] + e[0]) / 2
      let y = (s[1] + e[1]) / 2
      //中心点
      let center = [x, y]
      //斜率
      let k1 = (e[1] - s[1]) / (e[0] - s[0])
      let k2 = -1 / k1

      let b = y - k2 * center[0]
      let k2line_y = (x) => {
        return k2 * x + b
      }
      let k2line_x = (y) => {
        return (y - b) / k2
      }
      //几个交点
      let m_top = [k2line_x(lt[1]), lt[1]]
      let m_right = [rt[0], k2line_y(rt[0])]
      let m_left = [lt[0], k2line_y(lt[0])]
      let m_bottom = [k2line_x(lb[1]), lb[1]]

      console.log('top', m_top, 'right', m_right, 'left', m_left, 'bottom', m_bottom)
      let rect_front = []
      let rect_back = []

      //先处理上面的情况
      rect_front = [m_top, m_right, rb, lb, lt]
      rect_back = [m_top, rt, m_right]
      //反面正反clip-path相反
      //因为这时候正面是back，反面是front
      this.front.clip = rect_front
      this.back.clip = rect_back
      ;(() => {
        //下面构建矩阵
        let axis1 = [0, 1]
        let axis2 = vec2.create()
        let e = this.covertVec2Invert(m_top, this.back.m1)
        center = this.covertVec2Invert(center, this.back.m1)
        console.log('e', e, 'center', center)
        vec2.sub(axis2, e, center) //center指向e
        let cross = vec3.create()
        let angle = vec2.angle(axis1, axis2)
        vec2.cross(cross, axis1, axis2)
        let deg = (angle / Math.PI) * 180
        console.log(`deg`, deg)
        if (cross[2] == -1) {
          angle = -angle
        }

        let m = mat2d.create()
        //平移原点
        let m1 = mat2d.create()
        console.log(`center`, center)
        mat2d.translate(m1, m1, center)
        //console.log(center)

        //旋转角度
        let m2 = mat2d.create()
        mat2d.rotate(m2, m2, angle)
        console.log(`m2`, m2, angle)

        let m3 = mat2d.create()
        mat2d.mul(m3, m1, m2)

        //求逆
        let m3_i = mat2d.create()
        mat2d.invert(m3_i, m3)
        //对称
        let m4 = mat2d.create()
        mat2d.scale(m4, m4, [-1, 1])

        //Ax = b
        //B-1AB = b
        mat2d.mul(m, m, m3)
        mat2d.mul(m, m, m4)
        mat2d.mul(m, m, m3_i)
        console.log(m)
        this.back.m2 = m
      })()

      this.buildStyle(this.front)
      this.buildStyle(this.back)
    },
    covertVec2Invert(v, mat) {
      let invert_mat = mat2d.create()
      mat2d.invert(invert_mat, mat)
      let v2 = vec2.create()
      vec2.transformMat2d(v2, v, invert_mat)
      return v2
    },
    //翻过后状态
    step4() {
      let w = 100,
        h = 100
      let { rb, rt, lt, lb } = this.corrds
      //从左往右
      this.step2()
      let s = [-150, -50]
      let e = [-100, 0]

      let x = (s[0] + e[0]) / 2
      let y = (s[1] + e[1]) / 2
      //中心点
      let center = [x, y]
      //斜率
      let k1 = (e[1] - s[1]) / (e[0] - s[0])
      let k2 = -1 / k1

      let b = y - k2 * center[0]
      let k2line_y = (x) => {
        return k2 * x + b
      }
      let k2line_x = (y) => {
        return (y - b) / k2
      }
      //几个交点
      let m_top = [k2line_x(lt[1]), lt[1]]
      let m_right = [rt[0], k2line_y(rt[0])]
      let m_left = [lt[0] - w, k2line_y(lt[0] - w)]
      let m_bottom = [k2line_x(lb[1]), lb[1]]

      console.log('top', m_top, 'right', m_right, 'left', m_left, 'bottom', m_bottom)
      let rect_front = []
      let rect_back = []

      //先处理上面的情况
      rect_back = [m_top, m_left, [(-w / 2) * 3, h / 2], [-w / 2, h / 2], [-w / 2, -h / 2]]
      rect_front = [m_top, [(-w / 2) * 3, -h / 2], m_left]
      //反面正反clip-path相反
      //因为这时候正面是back，反面是front
      this.front.clip = rect_front
      this.back.clip = rect_back
      ;(() => {
        //下面构建矩阵
        let axis1 = [0, 1]
        let axis2 = vec2.create()
        let e = this.covertVec2Invert(m_top, this.front.m1)
        center = this.covertVec2Invert(center, this.front.m1)

        console.log('e', e, 'center', center)

        vec2.sub(axis2, e, center) //center指向e
        let cross = vec3.create()
        let angle = vec2.angle(axis1, axis2)
        vec2.cross(cross, axis1, axis2)
        let deg = (angle / Math.PI) * 180
        console.log(`deg`, deg)
        if (cross[2] == -1) {
          angle = -angle
        }

        let m = mat2d.create()
        //平移原点
        let m1 = mat2d.create()
        mat2d.translate(m1, m1, center)
        //console.log(center)

        //旋转角度
        let m2 = mat2d.create()
        mat2d.rotate(m2, m2, angle)
        console.log(`m2`, m2, angle)

        let m3 = mat2d.create()
        mat2d.mul(m3, m1, m2)

        //求逆
        let m3_i = mat2d.create()
        mat2d.invert(m3_i, m3)
        //对称
        let m4 = mat2d.create()
        mat2d.scale(m4, m4, [-1, 1])

        //Ax = b
        //B-1AB = b
        mat2d.mul(m, m, m3)
        mat2d.mul(m, m, m4)
        mat2d.mul(m, m, m3_i)
        console.log(m)
        this.front.m2 = m
      })()

      this.buildStyle(this.front)
      this.buildStyle(this.back)
    },
    init() {
      let w = 100
      let h = 100
      let lt = [-w / 2, -h / 2]
      let rt = [w / 2, -h / 2]
      let lb = [-w / 2, h / 2]
      let rb = [w / 2, h / 2]
      this.corrds = {
        lt,
        rt,
        lb,
        rb
      }
      this.w = w
      this.h = h
    },
    buildStyle(obj) {
      let { w, h } = this
      let end = mat2d.create()
      let { m1, m2, clip } = obj
      let { front, back } = clip
      mat2d.mul(end, end, m1)
      mat2d.mul(end, end, m2)

      let style = {}
      let transform = `matrix(${end.join(',')})`
      style.transform = transform
      let clipPath = ''
      if (clip.length) {
        let clipArray = clip
          .map((res) => {
            let [x, y] = res
            //当前页面坐标
            let p1 = [x, y]
            let p2 = vec2.create()
            vec2.copy(p2, p1)
            if (m1) {
              p2 = this.covertVec2Invert(p1, m1)
            } else {
              p2 = p1
            }
            p2[0] = p2[0] + w / 2
            p2[1] = p2[1] + h / 2

            return p2
          })
          .map((res) => {
            let [x, y] = res
            return x + 'px' + ' ' + y + 'px'
          })
        console.log(clipArray)

        clipPath = `polygon(${clipArray.join(',')})`
        style['clip-path'] = clipPath
      }

      obj.style = style
      console.log(style)
    }
  },
  mounted() {
    this.init()
  }
}
</script>
<style type="text/css" lang="scss">
.box {
  width: 100px;
  height: 100px;
  border: 1px solid #000;
  position: relative;
  transform-style: preserve-3d;
  margin: 100px auto;
  &-page {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
  }
  &-front {
    background: grey;
    width: 100px;
    height: 100px;
  }
  &-back {
    background: #646495;
    transform: scale(-1, 1);
    width: 100px;
    height: 100px;
  }
}
.box1 {
  width: 100px;
  height: 100px;
  border: 1px solid #000;
  transform: translate(10px, 0) rotate(30deg) scale(1.5, 1);
  clip-path: polygon(0 0, 50px 0, 50px 50px, 0 50px);
}
</style>
